package com.zeyu.soc.log.utils;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;

/**
 * <pre>
 * 简单封装Gson，实现JSON String<->Java Object的Mapper. 
 * 封装不同的输出风格, 使用不同的builder函数创建实例.
 * </pre>
 */
public class JsonUtils {

	// ================================================================
	// Constants
	// ================================================================

	// ================================================================
	// Fields
	// ================================================================

	// ================================================================
	// Constructors
	// ================================================================

	// ================================================================
	// Methods from/for super Interfaces or SuperClass
	// ================================================================

	// ================================================================
	// Public or Protected Methods
	// ================================================================

	/**
	 * 创建只输出非Null的Gson,建议在外部接口中使用.
	 */
	public static Gson getInstance() {
		return create();
	}

	/**
	 * 对象转换为JSON字符串
	 */
	public static String toJson(Object object) {
		Gson gson = create();
		return gson.toJson(object);
	}

	/**
	 * JSON字符串转换为对象
	 */
	public static Object fromJson(String json, Class<?> clazz) {
		Gson gson = create();
		return gson.fromJson(json, clazz);
	}

	/**
	 * JSON字符串转换为对象
	 */
	public static Object fromJson(String json, Type type) {
		Gson gson = create();
		return gson.fromJson(json, type);
	}

	// ================================================================
	// Getter & Setter
	// ================================================================

	// ================================================================
	// Private Methods
	// ================================================================

	/**
	 * 构建Gson转换器
	 */
	private static Gson create() {
		return create(false);
	}

	/**
	 * 构建Gson转换器
	 */
	private static Gson create(boolean formatter) {
		return create(formatter, false);
	}

	/**
	 * 构建Gson转换器
	 */
	private static Gson create(boolean formatter, boolean enableNull) {
		GsonBuilder builder = new GsonBuilder();
		// 增加对含有Class类型字段对象的支持
		builder.registerTypeHierarchyAdapter(Class.class, new JsonSerializer<Class<?>>() {

			@Override
			public JsonElement serialize(Class<?> src, Type type, JsonSerializationContext context) {
				return new JsonPrimitive(src.getName());
			}
		});
		builder.registerTypeHierarchyAdapter(Class.class, new JsonDeserializer<Class<?>>() {

			@Override
			public Class<?> deserialize(JsonElement element, Type type, JsonDeserializationContext context)
					throws JsonParseException {
				JsonPrimitive pri = (JsonPrimitive) element;
				try {
					return Class.forName(pri.getAsString());
				} catch (Exception e) {
					e.printStackTrace();
				}
				return null;
			}
		});
		// 格式化输出
		if (formatter) {
			builder.setPrettyPrinting();
		}
		// 允许null字段
		if (enableNull) {
			builder.serializeNulls();
		}

		return builder.create();
	}

	// ================================================================
	// Inner or Anonymous Class
	// ================================================================

	// ================================================================
	// Test Methods
	// ================================================================
	/**
	 * 测试
	 */
	public static void main(String[] args) {
		List<Map<String, Object>> list = new ArrayList<>();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("id", 1);
		map.put("pId", -1);
		map.put("name", "根节点");
		list.add(map);
		map = new HashMap<String, Object>();
		map.put("id", 2);
		map.put("pId", 1);
		map.put("name", "你好");
		map.put("open", true);
		list.add(map);
		String json = JsonUtils.toJson(list);
		System.out.println(json);
		Type type = new TypeToken<List<Map<String, Object>>>(){}.getType();
		System.out.println(JsonUtils.fromJson(json, type));
	}
}
